<?php

namespace services\statistics;

use common\models\base\Profession;
use common\models\member\Attr;
use Yii;
use common\models\base\PatientDiseases;
use common\models\clinic\Clinic;
use common\models\member\Member;
use common\models\patient\Consumption;
use common\models\patient\MonthRevisitingRecord;
use common\models\patient\RevisitingRecord;
use common\models\patient\User;
use common\helpers\ArrayHelper;
use common\components\Service;
use Exception;
use yii\db\Expression;

/**
 * Class ComplexReportService
 * @package services\statistics
 */
class ComplexReportService extends Service
{

    /**
     * 科室病人年度在诊周期病人人数汇总表
     *
     * @author wangxiang
     * @param array $condition
     * @return array
     */
    public function getTreatCycleData(array $condition): array
    {
        $query = Clinic::find()
            ->alias('c')
            ->leftJoin(MonthRevisitingRecord::tableName() . ' r', 'c.id = r.clinic_id AND r.project_id = ' . $condition['project_id'])
            ->where([
                'c.status' => Clinic::STATUS_ENABLE,
                'c.project_id' => $condition['project_id']
            ])
            ->select([
                'c.name clinic_name', 'r.clinic_id', 'c.sort clinic_sort',
                'GROUP_CONCAT(r.patient_card_id) patient_card_ids'
            ])
            ->groupBy([
                'c.id'
            ]);

        // 权限验证，如果是项目负责人能看到全部， 部门负责人看到当前部门下人员所有诊室的， 普通医助只能看自己诊室的， 客服看不到
        if (Member::IS_SUPER_NO == Yii::$app->user->identity->member->is_super) {
            $memberId = Yii::$app->user->identity->member_id;
            $attr = Yii::$app->services->attr->findInfo([
                'member_id' => $memberId,
                'project_id' => $condition['project_id'],
            ]);
            if (!$attr) {
                return [];
            }
            if (Attr::IS_DEPARTMENT_LEADER_NO == $attr->is_department_leader) {// 普通员工
                if ($attr->profession_id == Profession::ID_MEDICAL) {
                    // 医助
                    $query->andWhere(['r.clinic_id' => $attr->clinic_id]);
                } else {
                    return [];  // 其他岗位不给看
                }
            } else if (Attr::IS_DEPARTMENT_LEADER_YES == $attr->is_department_leader) {// 部门负责人【部门下所有员工】
                $clinicIdData = Attr::find()
                    ->where([
                        'department_id' => $attr->department_id,
                        'project_id' => $condition['project_id']
                    ])
                    ->select('clinic_id')
                    ->column();
                $query->andWhere(['r.clinic_id' => $clinicIdData]);
            }
        }

        return $this->_formatTreatCycleData($query->asArray()->all());
    }


    /**
     * 数据重组计算
     *
     * @author wangxiang
     * @param array $data
     * @return array
     */
    private function _formatTreatCycleData(array $data): array
    {
        $timeArr = range(1, 12);

        /*$clinicData = [];
        foreach ($data as $item) {
            $patientCardIdArr = explode(',', $item['patient_card_ids']);
            $clinicData[$item['clinic_id']]['arr'] = isset($clinicData[$item['clinic_id']]['arr']) ? array_merge($patientCardIdArr, $clinicData[$item['clinic_id']]['arr']) : $patientCardIdArr;
            $clinicData[$item['clinic_id']]['clinic_name'] = $item['clinic_name'];
            $clinicData[$item['clinic_id']]['clinic_sort'] = $item['clinic_sort'];
        }*/

        // 进行排序
        $data = ArrayHelper::arraySort($data, 'clinic_sort');

        // 数据重组
        $list =  [];
        foreach ($data as $item) {
            $patientCardArr = array_filter(explode(',', $item['patient_card_ids']));
            $tempArr['clinic_name'] = $item['clinic_name'];
            foreach ($timeArr as $timeKey) {
                $tempArr['month_' . $timeKey] = 0;
            }

            $this->_dealTreatCycleMonthNum(array_count_values(array_count_values($patientCardArr)), $tempArr);

            $list[] = $tempArr;
        }

       return $list;
    }

    /**
     * 计算每个阶段的数量
     *
     * @author wangxiang
     * @param array $arr
     * @param $tempArr
     */
    private function _dealTreatCycleMonthNum(array $arr, &$tempArr): void
    {
        $thanOneYearNum = 0;
        $thanTwoYearNum = 0;
        $thanThreeYearNum = 0;
        foreach ($arr as $key=> $val) {
            if ($key <= 12) {
                $tempArr['month_' . $key] = $val;
            } else if ($key >= 13 & $key <= 24) {
                // 一年以上
                $thanOneYearNum += $val;
            } else if ($key >= 25 && $key <= 36) {
                // 两年以上
                $thanTwoYearNum += $val;
            } else {
                // 三年以上
                $thanThreeYearNum += $val;
            }
        }
        $tempArr['than_one_year'] = $thanOneYearNum;
        $tempArr['than_two_year'] = $thanTwoYearNum;
        $tempArr['than_three_year'] = $thanThreeYearNum;
    }


    /**
     * 获取复诊构成表数据
     *
     * @author wangxiang
     * @param array $condition
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function getReferralCompriseData(array $condition, int $page = 0, int $pageSize = 0)
    {
        $query = User::find()
            ->alias('p')
            ->leftJoin(Member::tableName() . ' m', 'm.id = p.belong_assistant_id')
            ->where([
                'p.project_id' => $condition['project_id'],
                'p.status' => User::STATUS_ENABLE
            ])
            ->select([
                'p.id', 'p.patient_card_id', 'p.name', 'p.age', 'p.gender', 'p.reg_time',
                'p.kf_last_callback_time', 'p.yz_last_callback_time', 'p.kf_callback_count',
                'p.yz_callback_count', 'p.last_revisiting_time', 'p.patient_diseases_id',
                'p.patient_diseases_child_id', 'p.clinic_id', 'p.next_revisiting_time', 'm.realname',
                'GROUP_CONCAT(rs.is_sum) is_sums'
            ])
            ->groupBy([
                'p.patient_card_id'
            ]);

        // 挂号开始时间
        isset($condition['start_reg_time']) && $condition['start_reg_time'] && $query->andWhere(['>=', 'p.reg_time', $condition['start_reg_time']]);

        // 挂号结束时间
        isset($condition['end_reg_time']) && $condition['end_reg_time'] && $query->andWhere(['<', 'p.reg_time', $condition['end_reg_time']]);

        // 来院时间
//        if (isset($condition['start_last_revisiting_time']) && $condition['start_last_revisiting_time'] &&
//            isset($condition['end_last_revisiting_time']) && $condition['end_last_revisiting_time']) {
//            $query->andWhere(['between', 'r.revisting_time', $condition['start_last_revisiting_time'], $condition['end_last_revisiting_time']]);
//        }

        // 诊室
        isset($condition['clinic_id']) && $condition['clinic_id'] && $query->andWhere(['p.clinic_id' => $condition['clinic_id']]);

        // 病种
        isset($condition['patient_diseases_id']) && $condition['patient_diseases_id'] && $query->andWhere(['p.patient_diseases_id' => $condition['patient_diseases_id']]);

        // 判断选择时间内患者是否到诊
   //     if ($condition['s_time'] && $condition['e_time']) {
         if ($condition['start_last_revisiting_time'] && $condition['end_last_revisiting_time']) {
            $query->leftJoin(RevisitingRecord::tableName() . ' rs', "p.patient_card_id = rs.patient_card_id AND rs.project_id = {$condition['project_id']} AND rs.revisting_time BETWEEN {$condition['start_last_revisiting_time']} AND {$condition['end_last_revisiting_time']}");
            $query->addSelect('rs.id is_visit');
            if ($condition['is_visit'] == 1) {
                // 在时间区间到诊过
                $query->andWhere(['>', 'rs.id', 0]);
            } else if ($condition['is_visit'] == 2 ) {
                // 在时间区间未到诊
                $query->andWhere(['rs.id' => null]);
            }
        } else if ($condition['is_visit'] == 2) {
             $query->leftJoin(RevisitingRecord::tableName() . ' rs', "p.patient_card_id = rs.patient_card_id AND rs.project_id = {$condition['project_id']}");
             return [
                'page' => (int)$page,
                'pageSize' => (int)$pageSize,
                'total' => 0,
                'list' => [],
            ];
        } else {
             $query->leftJoin(RevisitingRecord::tableName() . ' rs', "p.patient_card_id = rs.patient_card_id AND rs.project_id = {$condition['project_id']}");
             $query->addSelect(new Expression('1 is_visit'));
        }

        // 权限验证，如果是项目负责人能看到全部， 部门负责人看到当前部门下人员所有诊室的， 普通医助只能看自己诊室的， 客服看不到
        if (Member::IS_SUPER_NO == Yii::$app->user->identity->member->is_super) {
            $memberId = Yii::$app->user->identity->member_id;
            $attr = Yii::$app->services->attr->findInfo([
                'member_id' => $memberId,
                'project_id' => $condition['project_id'],
            ]);
            if (!$attr) {
                return [];
            }
            if (Attr::IS_DEPARTMENT_LEADER_NO == $attr->is_department_leader) {// 普通员工
                if ($attr->profession_id == Profession::ID_MEDICAL) {
                    // 医助
                    $query->andWhere(['p.clinic_id' => $attr->clinic_id]);
                } else {
                    return [];  // 其他岗位不给看
                }
            } else if (Attr::IS_DEPARTMENT_LEADER_YES == $attr->is_department_leader) {// 部门负责人【部门下所有员工】
                $clinicIdData = Attr::find()
                    ->where([
                        'department_id' => $attr->department_id,
                        'project_id' => $condition['project_id']
                    ])
                    ->select('clinic_id')
                    ->column();
                $query->andWhere(['p.clinic_id' => $clinicIdData]);
            }
        }

        // 总数
        $total = $query->count();

        // 分页
        if ($page && $pageSize) {
            $query->limit($pageSize)->offset(($page - 1) * $pageSize);
        }

        $list = $query
            ->orderBy(['p.reg_time' => SORT_DESC])
            ->asArray()
            ->all();

        $list = $this->_formatReferralCompriseData($condition, $list);

        return [
            'page' => (int)$page,
            'pageSize' => (int)$pageSize,
            'total' => (int)$total,
            'list' => $list,
        ];
    }


    /**
     * 格式化并处理复诊构成表数据
     *
     * @author wangxiang
     * @param array $condition
     * @param array $data
     * @return array
     */
    private function _formatReferralCompriseData(array $condition, array $data): array
    {
        $patientCardIdArr = []; // 患者卡号
        $clinicIdArr = [];  // 诊室id
        $patientDiseasesIdArr = []; // 病种id
        foreach ($data as $item) {
            $patientCardIdArr[] = $item['patient_card_id'];
            $clinicIdArr[] = $item['clinic_id'];
            $patientDiseasesIdArr[] = $item['patient_diseases_id'];
            $patientDiseasesIdArr[] = $item['patient_diseases_child_id'];
        }

        // 获取每个患者的总消费金额
        $consumptionData = Consumption::find()
            ->where([
                'project_id' => $condition['project_id'],
                'patient_card_id' => $patientCardIdArr
            ])
            ->select([
                'SUM(reality_money) all_money',
                'patient_card_id'
            ])
            ->groupBy([
                'patient_card_id'
            ])
            ->indexBy('patient_card_id')
            ->asArray()
            ->all();

        // 获取患者的诊室
        $clinicData = Clinic::find()
            ->where(['id' => $clinicIdArr])
            ->select(['name', 'id'])
            ->indexBy('id')
            ->asArray()
            ->all();

        // 获取患者的病种
        $diseasesIdData = PatientDiseases::find()
            ->where(['id' => $patientDiseasesIdArr])
            ->select(['id', 'diseases_name'])
            ->indexBy('id')
            ->asArray()
            ->all();

        // 区间消费
        if (isset($condition['start_last_revisiting_time']) && $condition['start_last_revisiting_time'] &&
            isset($condition['end_last_revisiting_time']) && $condition['end_last_revisiting_time']) {
            $sectionMoneyArr = Consumption::find()
                ->where([
                    'project_id' => $condition['project_id'],
                    'patient_card_id' => $patientCardIdArr
                ])
                ->andWhere(['between', 'clinic_time', $condition['start_last_revisiting_time'], $condition['end_last_revisiting_time']])
                ->select([
                    'SUM(reality_money) section_money', 'patient_card_id'
                ])
                ->groupBy('patient_card_id')
                ->indexBy('patient_card_id')
                ->asArray()
                ->all();
        }

        $list = [];

        foreach ($data as $item) {
            $lastCallbackTime = $item['kf_last_callback_time'] > $item['yz_last_callback_time'] ? $item['kf_last_callback_time'] : $item['yz_last_callback_time'];
            $diseases = $diseasesIdData[$item['patient_diseases_id']]['diseases_name'] ?? '';
            $childDiseases = $diseasesIdData[$item['patient_diseases_child_id']]['diseases_name'] ?? '';
            $revisitingCount = array_count_values(explode(',', $item['is_sums']))[RevisitingRecord::IS_SUM_YES] ?? 0;

            if (isset($condition['start_last_revisiting_time']) && $condition['start_last_revisiting_time'] &&
                isset($condition['end_last_revisiting_time']) && $condition['end_last_revisiting_time']) {
                $sectionMoney = $sectionMoneyArr[$item['patient_card_id']]['section_money'] ?? '/';
            } else {
                $sectionMoney = $consumptionData[$item['patient_card_id']]['all_money'] ?? '/';
            }

            $list[] = [
                'id' => $item['id'],
                'is_visit' => $item['is_visit'] ? 1 : 0,
                'info' => $item['name'] . ' ' . (User::$genders[$item['gender']] ?? '未知') . ' ' . $item['age'],
                'reg_time' => $item['reg_time'] ? date('Y-m-d', $item['reg_time']) : '',
                'clinic_name' => $clinicData[$item['clinic_id']]['name'] ?? '',
                'revisiting_count' => $revisitingCount,
                'last_callback_time' => $lastCallbackTime ? date('Y-m-d', $lastCallbackTime) : '',
                'callback_count' => $item['kf_callback_count'] + $item['yz_callback_count'],
                'last_revisiting_time' => $item['last_revisiting_time'] ? date('Y-m-d', $item['last_revisiting_time']) : '',
                'diseases' => $childDiseases ?: $diseases,
                'next_revisiting_time' => $item['next_revisiting_time'] ? date('Y-m-d',$item['next_revisiting_time']) : '',
                'belong_assistant_name' => $item['realname'] ?? '',
                'section_money' => $sectionMoney,
                'all_money' => $consumptionData[$item['patient_card_id']]['all_money'] ?? '/',
                //'is_visit' => $item['next_revisiting_time'] >= strtotime(date('Y-m-d')) ? 1 : 0
            ];
        }

        return $list;
    }


    /**
     * 保存患者月到诊统计记录
     *
     * @author wangxiang
     * @param array $data
     * @return int
     * @throws Exception
     */
    public function savePatientMonthRevisitRecord(array $data): int
    {
        $model = MonthRevisitingRecord::find()
            ->where([
                'project_id' => $data['project_id'],
                'clinic_id' => $data['clinic_id'],
                'patient_card_id' => $data['patient_card_id'],
                'month' => strtotime(date('Y-m', $data['month'])),
                'status' => MonthRevisitingRecord::STATUS_ENABLE
            ])
            ->one();

        if (!$model) {
            $model = new MonthRevisitingRecord;
            $model->project_id = $data['project_id'];
            $model->clinic_id = $data['clinic_id'];
            $model->patient_card_id = $data['patient_card_id'];
            $model->month = strtotime(date('Y-m', $data['month']));
            if (!$model->save()) {
                throw new Exception(json_encode($model->getFirstErrors()), 500);
            }
        }

        return $model->id;
    }
}
